import isEqual from 'lodash/isEqual';

export function transformArrayToObject(
  originalSchema: any,
  arrayData: any[]
): any {
  if (Object.keys(originalSchema).length == 0) {
    return {};
  }
  
  const transformedResult: any = {};

  // Function to find the array key in a nested schema
  function findArrayKey(schema: any): string | null {
    for (const key in schema.properties) {
      if (schema.properties[key].type === 'array') {
        return key;
      } else if (schema.properties[key].type === 'object') {
        const nestedKey = findArrayKey(schema.properties[key]);
        if (nestedKey) {
          return `${key}.${nestedKey}`;
        }
      }
    }
    return null;
  }

  const arrayKeyPath = findArrayKey(originalSchema);
  if (!arrayKeyPath) {
    return arrayData.reduce((acc, item) => {
      for (const key in item) {
        if (!acc[key]) {
          acc[key] = item[key];
        } else if (typeof acc[key] === 'object' && typeof item[key] === 'object') {
          acc[key] = { ...acc[key], ...item[key] };
        }
      }
      return acc;
    }, {});
  }

  const arrayKeyParts = arrayKeyPath.split('.');
  const arrayKey = arrayKeyParts.pop();
  if (!arrayKey) {
    throw new Error("Array key not found in schema");
  }

  const parentSchema = arrayKeyParts.reduce((schema, key) => schema.properties[key], originalSchema);
  const itemSchema = parentSchema.properties[arrayKey].items;
  if (!itemSchema) {
    throw new Error("Item schema not found for array key");
  }

  // Initialize the array in the transformed result
  let currentLevel = transformedResult;
  arrayKeyParts.forEach(part => {
    if (!currentLevel[part]) {
      currentLevel[part] = {};
    }
    currentLevel = currentLevel[part];
  });
  currentLevel[arrayKey] = [];

  // Helper function to check if an object is already in the array
  function isDuplicateObject(array: any[], obj: any): boolean {
    return array.some(existingItem => isEqual(existingItem, obj));
  }

  // Helper function to validate if an object follows the schema
  function isValidObject(obj: any, schema: any): boolean {
    return Object.keys(schema.properties).every(key => {
      return obj.hasOwnProperty(key) && typeof obj[key] === schema.properties[key].type;
    });
  }

  // Iterate over each item in the arrayData
  arrayData.forEach(item => {
    let currentItem = item;
    arrayKeyParts.forEach(part => {
      if (currentItem[part]) {
        currentItem = currentItem[part];
      }
    });

    // Copy non-array properties from the parent object
    for (const key in parentSchema.properties) {
      if (key !== arrayKey && currentItem.hasOwnProperty(key) && !currentLevel.hasOwnProperty(key)) {
        currentLevel[key] = currentItem[key];
      }
    }

  // Ensure that the currentItem[arrayKey] is an array before mapping
  if (Array.isArray(currentItem[arrayKey])) {
    currentItem[arrayKey].forEach((subItem: any) => {
      if (typeof subItem === 'object' && subItem !== null && isValidObject(subItem, itemSchema)) {
        // For arrays of objects, add only unique objects
        const transformedItem: any = {};
        let hasValidData = false;

        for (const key in itemSchema.properties) {
          if (subItem.hasOwnProperty(key) && subItem[key] !== undefined) {
            transformedItem[key] = subItem[key];
            hasValidData = true;
          }
        }

        if (hasValidData && !isDuplicateObject(currentLevel[arrayKey], transformedItem)) {
          currentLevel[arrayKey].push(transformedItem);
        }
      }
    });
  } else {
    console.warn(`Expected an array at ${arrayKey}, but found:`, currentItem[arrayKey]);
  }

    // Handle merging of array properties
    for (const key in parentSchema.properties) {
      if (parentSchema.properties[key].type === 'array' && Array.isArray(currentItem[key])) {
        if (!currentLevel[key]) {
          currentLevel[key] = [];
        }
        currentItem[key].forEach((value: any) => {
          if (!currentLevel[key].includes(value) && !isDuplicateObject(currentLevel[arrayKey], value)) {
            currentLevel[key].push(value);
          }
        });
      }
    }
  });

  return transformedResult;
}